package com.hzw.saas.web.admin.sys.controller;

import java.util.Objects;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hzw.saas.api.sys.dto.SysUserAccountDto;
import com.hzw.saas.api.sys.service.ISysUserService;
import com.hzw.saas.common.config.annotation.SysLog;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.security.utils.SecurityUtils;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.common.verify.service.IVerifyService;
import com.hzw.saas.web.admin.enums.VerifyMode;
import com.hzw.saas.web.admin.sys.param.PwdForgetParam;
import com.hzw.saas.web.admin.sys.param.PwdResetParam;
import com.hzw.saas.web.admin.sys.param.SysUserAddParam;
import com.hzw.saas.web.admin.sys.param.SysUserModifyParam;
import cn.hutool.core.util.StrUtil;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiOperationSort;
import lombok.RequiredArgsConstructor;

/**
 * <p>
 *
 * </p>
 *
 * @author sonam
 * @since 2021/2/22 15:01
 */
// @ApiIgnore
@Api(tags = "系统用户信息")
@RestController
@RequiredArgsConstructor
public class SysUserController {

    private final ISysUserService sysUserService;
    private final PasswordEncoder passwordEncoder;

    private final IVerifyService verifyService;

    // @SysLog(operation = "添加系统用户")
    // @ApiOperation(value = "添加系统用户", notes = "只有管理员才能够添加系统用户（管理员用户）")
    // @PutMapping("/sys/user/add")
    // @ApiOperationSort(1)
    public ResponseEntity<String> addSysUser(@Validated @RequestBody SysUserAddParam sysUserAddParam) {
        SysUserAccountDto SysUserAccountDto = MapperUtil.nf().map(sysUserAddParam, SysUserAccountDto.class);
        sysUserService.add(SysUserAccountDto);
        return ResponseEntity.ok("添加系统用户成功");
    }

    @PutMapping("/password/forget")
    @SysLog(operation = "忘记密码", mode = 3)
    @ApiOperation(value = "忘记密码", notes = "忘记密码时使用手机号设置新密码，无需登录")
    @ApiOperationSort(11)
    public ResponseEntity<Boolean> forgetPassword(@Validated @RequestBody PwdForgetParam param) {
        AssertUtil.assertThrow("手机和邮箱不能同时为空", StrUtil.isAllBlank(param.getPhoneNo(), param.getEmail()));
        boolean verifySms = false;
        boolean verifyEmail = false;
        // 检查验证码
        if (StringUtils.isNotBlank(param.getPhoneNo())) {
            verifySms = verifyService.verify(param.getPhoneNo(), param.getVerifyCode());
        }
        if (StringUtils.isNotBlank(param.getEmail())) {
            verifyEmail = verifyService.verify(param.getEmail(), param.getVerifyCode());
        }
        AssertUtil.assertThrow("验证码错误", !verifySms && !verifyEmail);

        SysUserAccountDto sysUser;
        if (verifySms) {
            // 验证用户存在
            sysUser = sysUserService.get(new SysUserAccountDto().setPhoneNo(param.getPhoneNo()));
            AssertUtil.assertThrow("手机号不存在", Objects.isNull(sysUser));
        } else {
            // 验证用户存在
            sysUser = sysUserService.get(new SysUserAccountDto().setEmail(param.getEmail()));
            AssertUtil.assertThrow("邮箱不存在", Objects.isNull(sysUser));
        }
        // 更新密码
        boolean reset = sysUserService.resetPassword(sysUser.getUserId(), param.getPassword());
        return ResponseEntity.ok(reset);
    }

    @PutMapping("/sys/user/rest")
    @SysLog(operation = "修改密码(通过原密码)", mode = 3)
    @ApiOperation(value = "修改密码(通过原密码)", notes = "修改密码(通过原密码)")
    @ApiOperationSort(12)
    public ResponseEntity<Boolean> updateSysUser(@Validated @RequestBody SysUserModifyParam param) {
        String userId = SecurityUtils.getUser().getUserId();
        SysUserAccountDto SysUserAccountDto = sysUserService.get(userId);
        String encodedPassword = SysUserAccountDto.getPassword();
        // 密码不正确
        if (!passwordEncoder.matches(param.getOldPassword(), encodedPassword)) {
            throw new BadCredentialsException("账号或密码不正确");
        }
        boolean resetPassword = sysUserService.resetPassword(userId, param.getPassword());
        return ResponseEntity.ok(resetPassword);
    }

    @PutMapping("/password")
    @SysLog(operation = "修改密码(通过验证码)", mode = 3)
    @ApiOperation(value = "修改密码(通过验证码)", notes = "处理用户修改密码请求，需用户已登录，使用邮箱或手机验证")
    @ApiOperationSort(13)
    public ResponseEntity<Boolean> changePassword(@Validated @RequestBody PwdResetParam param) {
        VerifyMode verifyMode = VerifyMode.instance(param.getVerifyMode(), true);
        String userId = SecurityUtils.getUser().getUserId();
        SysUserAccountDto sysUser = sysUserService.get(userId);
        AssertUtil.assertThrow("用户信息丢失", Objects.isNull(sysUser));
        boolean verify = false;
        switch (Objects.requireNonNull(verifyMode)) {
            case PHONE:
                verify = verifyService.verify(sysUser.getPhoneNo(), param.getVerifyCode());
                break;
            case EMAIL:
                verify = verifyService.verify(sysUser.getEmail(), param.getVerifyCode());
        }
        AssertUtil.assertThrow("验证码错误", !verify);
        boolean reset = sysUserService.resetPassword(userId, param.getPassword());
        return ResponseEntity.ok(reset);
    }

}
